"""GitHub repository downloader."""

import os
import shutil
from pathlib import Path
from typing import Optional
import git
from github import Github
from rich.console import Console

from .config import Config

console = Console()

class GitHubDownloader:
    """Handles downloading and managing GitHub repositories."""
    
    def __init__(self, github_token: Optional[str] = None):
        self.github = Github(github_token or Config.GITHUB_TOKEN)
        self.repos_dir = Path(Config.REPOS_DIR)
        self.repos_dir.mkdir(exist_ok=True)
    
    def download_repository(self, repo_url: str, branch: str = "main") -> Path:
        """
        Download a GitHub repository.
        
        Args:
            repo_url: Repository URL (https or git)
            branch: Branch to checkout
            
        Returns:
            Local path to the downloaded repository
        """
        try:
            # Parse repository URL
            if repo_url.endswith('.git'):
                repo_url = repo_url[:-4]
            
            if 'github.com' not in repo_url:
                raise ValueError("Only GitHub repositories are supported")
            
            # Extract owner and repo name
            parts = repo_url.split('github.com/')[-1].split('/')
            owner, repo_name = parts[0], parts[1]
            
            # Get repository info
            repo = self.github.get_repo(f"{owner}/{repo_name}")
            
            # Create local directory
            local_path = Config.get_repo_path(repo_url)
            
            if local_path.exists():
                console.print(f"[yellow]Repository already exists at {local_path}, updating...[/yellow]")
                self._update_repository(local_path, branch)
            else:
                console.print(f"[green]Downloading repository {owner}/{repo_name}...[/green]")
                self._clone_repository(repo.clone_url, local_path, branch)
            
            console.print(f"[green]Repository downloaded to {local_path}[/green]")
            return local_path
            
        except Exception as e:
            console.print(f"[red]Error downloading repository: {e}[/red]")
            raise
    
    def _clone_repository(self, clone_url: str, local_path: Path, branch: str):
        """Clone a repository."""
        try:
            git.Repo.clone_from(
                clone_url,
                local_path,
                branch=branch,
                depth=1  # Shallow clone for faster download
            )
        except git.GitCommandError as e:
            # Try with 'master' branch if 'main' fails
            if branch == "main":
                git.Repo.clone_from(
                    clone_url,
                    local_path,
                    branch="master",
                    depth=1
                )
            else:
                raise
    
    def _update_repository(self, local_path: Path, branch: str):
        """Update an existing repository."""
        try:
            repo = git.Repo(local_path)
            origin = repo.remotes.origin
            origin.pull(branch)
        except git.GitCommandError:
            # Try with 'master' branch if 'main' fails
            if branch == "main":
                origin.pull("master")
            else:
                raise
    
    def remove_repository(self, repo_url: str) -> bool:
        """Remove a locally stored repository."""
        local_path = Config.get_repo_path(repo_url)
        if local_path.exists():
            shutil.rmtree(local_path)
            console.print(f"[green]Removed repository at {local_path}[/green]")
            return True
        return False
    
    def list_repositories(self) -> list[str]:
        """List all locally stored repositories."""
        if not self.repos_dir.exists():
            return []
        
        repos = []
        for item in self.repos_dir.iterdir():
            if item.is_dir() and (item / '.git').exists():
                repos.append(item.name)
        
        return repos